﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;
namespace RPG1
{
    public partial class FormMain : Form
    {
        List<Role> heros;
        List<Role> monsters;
        List<RPGControls> controls;
        public FormMain()
        {
            InitializeComponent();
        }
        private void FormMain_Load(object sender, EventArgs e)
        {
            controls = new List<RPGControls>();
            controls.Add(new RPGControls(picBoxHero1, labelBottomHero1, labelTopHero1, picBoxWeapon1));
            controls.Add(new RPGControls(picBoxHero2, labelBottomHero2, labelTopHero2));
            controls.Add(new RPGControls(pictureBoxMonster1, labelBottomMonster1, labelTopMonster1, picBoxWeapon2));
            controls.Add(new RPGControls(pictureBoxMonster2, labelBottomMonster2, labelTopMonster2));
            try
            {
                heros = readObjs<List<Role>>("D:/roles/init/heros.xml");
                monsters = readObjs<List<Role>>("D:/roles/init/monsters.xml");
            } catch (Exception e1)  {
                makeRoles();
            }
            updateUI();
            heros.Sort(delegate (Role x, Role y) { return y.Speed.CompareTo(x.Speed); });
            monsters.Sort(delegate (Role x, Role y) { return y.Speed.CompareTo(x.Speed); });
            if(heros[0].Speed < monsters[0].Speed) {
                Delay(100000);
                 foreach ( Role monster in monsters) {
                    attack(monster, heros[0]);
                    if (heros[0].CurrentLife <= 0) {
                        controls[heros[0].Id].died();
                        heros.Remove(heros[0]);
                    }
                }
                if (heros.Count == 0) {
                    MessageBox.Show("You Loss!");
                    return;
                }
            }
        }
        private void updateUI()
        {
            foreach(Role hero in heros) {
                controls[hero.Id].initLocation(hero.OriginaLocation);
                controls[hero.Id].updateBlood(hero.CurrentLife, hero.OriginalLife);
            }
            foreach (Role monster in monsters)
            {
                controls[monster.Id].initLocation(monster.OriginaLocation);
                controls[monster.Id].updateBlood(monster.CurrentLife, monster.OriginalLife);
            }
        }
        private void picBoxAttack_Click(object sender, EventArgs e) {
            foreach (Role hero in heros)
            {
                attack(hero,monsters[0]);
                if (monsters[0].CurrentLife <= 0) {
                    controls[monsters[0].Id].died();
                    monsters.Remove(monsters[0]);
                    if (monsters.Count == 0) {
                        MessageBox.Show("You Win!");
                        picBoxAttack.Enabled = false;
                        return;
                    }
                }
            }
           
            foreach (Role monster in monsters) {
                attack(monster,heros[0]);
                if (heros[0].CurrentLife <= 0)
                {
                    controls[heros[0].Id].died();
                    heros.Remove(monsters[0]);
                    if (heros.Count == 0)
                    {
                        MessageBox.Show("You Loss!");
                        picBoxAttack.Enabled = false;
                        return;
                    }
                }
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string datetime = string.Format("{0:yyyy年MM月dd日HH时mm分ss秒ffff}", DateTime.Now);
            string path = "D:/roles/" + datetime;
            if (!Directory.Exists(path))
                Directory.CreateDirectory(path);
            saveObjs(path + "/heros.xml", heros);
            saveObjs(path + "/monsters.xml", monsters);
            MessageBox.Show("存档成功! -- " + path);
        }
        private void saveObjs(string path, Object obj)
        {
            XmlSerializer serializer = new XmlSerializer(obj.GetType());
            TextWriter writer = new StreamWriter(path);
            serializer.Serialize(writer, obj);
            writer.Close();
        }
        private void readToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
            {
                DirectoryInfo dir = new DirectoryInfo(@folderBrowserDialog1.SelectedPath.ToString());
                string path = dir.ToString();
                heros = readObjs<List<Role>>(path + "/heros.xml");
                monsters = readObjs<List<Role>>(path + "/monsters.xml");
                updateUI();
                picBoxAttack.Enabled = true;
            }
        }
        public T readObjs<T>(string path) where T : class
        {
            try
            {
                using (StreamReader sr = new StreamReader(path))
                {
                    XmlSerializer serializer = new XmlSerializer(typeof(T));
                    return serializer.Deserialize(sr) as T;
                }
            }catch (Exception ex){
                throw new Exception("将XML转换成实体对象异常", ex);
            }
            //StreamReader sr = new StreamReader(path);
            //XmlSerializer serializer = new XmlSerializer(typeof(T));
            //return serializer.Deserialize(sr) as T;
        }
       
        // 延时效果
        public void Delay(int times){
            for (int i = 0; i < times; i++)
                Application.DoEvents();
        }
       
        // 攻击
        public  void attack(Role me, Role enemy){

            int diffX = controls[enemy.Id].PicRole.Location.X + controls[enemy.Id].PicRole.Width - controls[me.Id].PicRole.Location.X;
            int diffY = controls[enemy.Id].PicRole.Location.Y - controls[me.Id].PicRole.Location.Y - 10;
            controls[me.Id].move(diffX, diffY);
            WriteLog("攻击前"+enemy.ToString() + ", me.getAttack()=" + me.getAttack() +",  enemy.getDefense()=" + enemy.getDefense());
            int hurt = me.getAttack() - enemy.getDefense();
            if (hurt <= 0) hurt = 0;
            enemy.CurrentLife -= hurt;
            WriteLog("攻击后" + enemy.ToString() + ", me.getAttack()=" + me.getAttack() +", enemy.getDefense()=" + enemy.getDefense());
            if (enemy.CurrentLife <= 0)
                enemy.CurrentLife = 0;
            controls[enemy.Id].updateBlood(enemy.CurrentLife, enemy.OriginalLife);
            controls[me.Id].goBack(me.OriginaLocation);
        }

        public void makeRoles() {
            heros = new List<Role>();
            monsters = new List<Role>();

            Weapon wpnMagician1 = new Weapon("wand", 1, 1, 10, 0, 3);
            Weapon wpnWarrior1 = new Weapon("sword", 1, 1, 20, 2, 1);
            Weapon wpnNecromancer1 = new Weapon("magicRing", 1, 1, 30, 2, 3);
            Weapon wpnMinotaur1 = new Weapon("axe", 1, 1, 30, 0, 3);
            RPGControls cl = controls[0];
            Magician magician1 = new Magician(0, "magician1", 100, 100, 50, 0, 5, 9, cl.PicRole.Location, cl.PicRole.Location, wpnMagician1);
            cl = controls[1];
            Warrior warrior1 = new Warrior(1, "warrior1", 100, 100, 80, 30, 3, 6, cl.PicRole.Location, cl.PicRole.Location, wpnWarrior1);
            cl = controls[2];
            Necromancer necromancer1 = new Necromancer(2, "necromancer1", 100, 7, 100, 30, 10, 8, cl.PicRole.Location, cl.PicRole.Location, wpnNecromancer1);
            cl = controls[3];
            Minotaur minotaur1 = new Minotaur(3, "minotaur1", 100, 100, 10, 10, 4, 5, cl.PicRole.Location, cl.PicRole.Location, wpnMinotaur1);

            heros.Add(magician1);
            heros.Add(warrior1);
            monsters.Add(necromancer1);
            monsters.Add(minotaur1);
        }

        // [INFO]日志记录
        public void WriteLog(string msg)
        {
            string filePath = AppDomain.CurrentDomain.BaseDirectory + "Log";
            if (!Directory.Exists(filePath))  {
                Directory.CreateDirectory(filePath);
            }
            string logPath = AppDomain.CurrentDomain.BaseDirectory + "Log\\" + DateTime.Now.ToString("yyyy-MM-dd") + ".txt";
            try
            {
                using (StreamWriter sw = File.AppendText(logPath))
                {
                    sw.WriteLine("[INFO] " + DateTime.Now.ToString("yyyy - MM - dd HH: mm:ss") + "-->" + msg);
                    sw.Flush();
                    sw.Close();
                    sw.Dispose();
                }
            } catch (IOException e) {
                using (StreamWriter sw = File.AppendText(logPath))
                {
                    sw.WriteLine("[ERROR] " + DateTime.Now.ToString("yyy-MM-dd HH:mm:ss") + "-->" + e.Message);
                    sw.Flush();
                    sw.Close();
                    sw.Dispose();
                }
            }
        }
    }
}